package com.bradz.mymovies;

import io.socket.SocketIO;
import io.socket.IOCallback;
import io.socket.IOAcknowledge;
import io.socket.SocketIOException;

import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import org.apache.http.NameValuePair;
import org.apache.http.cookie.Cookie;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.webkit.CookieSyncManager;
import android.widget.TextView;

public class ClassNetworkHelper {

	ClassHttpHelper helper;
	private Context context;
	//private boolean pass_class;
	private Class<?> next_activity;
	//private String post_controller;
	private boolean applying;
	private ClassAndroidLogger logger;
	private SocketIO socket;
	//private ApplicationGlobalVars globals;
	
	ClassNetworkHelper(Context context, String base_url, ApplicationGlobalVars globals){
		this.context = context;
		CookieSyncManager.createInstance(context);
		helper = new ClassHttpHelper(base_url,globals);
		applying = false;
		logger = new ClassAndroidLogger("ClassNetworkHelper");
	}
	
	ClassNetworkHelper(Context context, ApplicationGlobalVars globals){
		this.context = context;
		CookieSyncManager.createInstance(context);
		helper = new ClassHttpHelper(context.getString(R.string.network_address),globals);
		applying = false;
		logger = new ClassAndroidLogger("ClassNetworkHelper");
	}
	
	public boolean applying(){
		return applying;
	}
	
	public void log_out_network(Handler handler){
		log_out_network_task login = new log_out_network_task();
		login.handler = handler;
		login.execute();
		logger.info("Logging out of network");
	}
	
	public void log_into_network(){
		//pass_class = true;
		//this.next_activity = next_activity;
		log_into_network_task login = new log_into_network_task();
		logger.info("Logging into network");
		
		login.execute();
	
		logger.info("Cookie Store Size: " + helper.get_client().get_cookies().getCookies().size());
	}
	
	public void send_message(List<NameValuePair> pairs, String routing_string){
		send_message_task task = new send_message_task(new ArrayList<NameValuePair>(pairs), routing_string);
		task.execute();
	}
	
	public SocketIO init_socket(){

		String host = helper.get_base_url();
		logger.info(host);
		
		Properties headers = new Properties();
		
		logger.info("Cookie Store Size: " + helper.get_client().get_cookies().getCookies().size());
		
		for (Cookie cookie : helper.get_client().get_cookies().getCookies()){
			
			logger.info(cookie.getDomain());
			logger.info(cookie.getName());
			logger.info(cookie.getValue());
			
			if (helper.get_base_url().contains(cookie.getDomain())){
				logger.info("Cookie Properties Set");
				Date date = new Date();
			    date.setTime(date.getTime()+(100*24*60*60*1000));
				String expires = "; expires="+date+";";
				headers.setProperty("Cookie", cookie.getName()+"="+cookie.getValue()+expires+" path=/;domain="+cookie.getDomain());
			}
		}
		
		try {
			logger.info("Creating Socket");
			socket = new SocketIO(host,headers);
	        socket.connect(new IOCallback() {
	            @Override
	            public void onMessage(JSONObject json, IOAcknowledge ack) {
	                try {
	                    System.out.println("Server said:" + json.toString(2));
	                } catch (JSONException e) {
	                    e.printStackTrace();
	                }
	            }
	
	            @Override
	            public void onMessage(String data, IOAcknowledge ack) {
	                System.out.println("Server said: " + data);
	            }
	
	            @Override
	            public void onError(SocketIOException socketIOException) {
	                System.out.println("an Error occured");
	                socketIOException.printStackTrace();
	            }
	
	            @Override
	            public void onDisconnect() {
	                System.out.println("Connection terminated.");
	            }
	
	            @Override
	            public void onConnect() {
	                System.out.println("Connection established");
	            }
	
	            @Override
	            public void on(String event, IOAcknowledge ack, Object... args) {
	                System.out.println("Server triggered event '" + event + "'");
	                
	                if(event.equals("mymovies_media")){
	                	try {
							JSONObject result_object = new JSONObject(args[0].toString());
							String message = result_object.getString("message");
							String developer_payload = result_object.getString("payload");
							logger.info("Received Message!: " + message);
							helper.get_globals().set_buffer(message);
							logger.info("Current Buffer: " + helper.get_globals().get_buffer());
							//This will hopefully reset the mediaplayer and add the buffer to what it is currently playing...
							helper.get_globals().reset_media_intent(developer_payload);
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
	                }
	            }
	        });
	        
			return socket;
	        
		} catch (MalformedURLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		return null;
	}
	
	//Make sure that the network is active and working...
	private class log_into_network_task extends AsyncTask<Void, Void, Void> {
		
		boolean intent_started;
		boolean returned_error;
		boolean test_login;
		TextView chat_box;
		ArrayList<NameValuePair> pairs;
		
		log_into_network_task(/*boolean test_login, ArrayList<NameValuePair> pairs*/){
			//this.test_login = test_login;
			//this.pairs = new ArrayList<NameValuePair>(pairs);
			//this.chat_box = chat_box;
		}
		
		@Override
        protected void onPreExecute() {
			intent_started = returned_error = false;
			logger.info("Log into network init");
		}
		
		@Override
		protected Void doInBackground(Void... args) {
			synchronized (helper) {
				//Saves the new user. If the user isn't new, sends back an error with the user in the db
				logger.info("Sending post");
				
				//Set/Retrieve the cookie store
				helper.getResponsefromURL("android/call/");
				logger.info("Cookie Store Size: " + helper.get_client().get_cookies().getCookies().size());
				
				//Establish a connection with the server socket
				socket = init_socket();
				
				//try {
					
					//Copy the client session cookie to the socket and try to login
					//JSONObject emitting_object = new JSONObject();
					//for(NameValuePair pair : pairs){
					//	emitting_object.put(pair.getName(), pair.getValue());
					//}
			        //socket.emit("login", emitting_object);
			        
			        //Establish a session with the server
			        
					//JSONObject result_object = new JSONObject(helper.postResponsefromURL("login/", pairs));
					//logger.info(result_object.toString());
				//} catch (JSONException e) {
					// TODO Auto-generated catch block
				//	e.printStackTrace();
				//}
			}
			return null;
		}
		
		@Override
	    protected void onPostExecute(Void v) {
		}
	}
	
	//Make sure that the network is active and working...
	private class log_out_network_task extends AsyncTask<Void, Void, Void> {
		
		Handler handler = null;
		JSONObject result_array = null;
		boolean returned_error = false;
		
		@Override
        protected void onPreExecute() {
			logger.info("Network Logout Task Init");
		}
		
		@Override
		protected Void doInBackground(Void... container) {
			synchronized (helper) {
				try {
					logger.info("Requesting logout");
					result_array = new JSONObject(helper.getResponsefromURL("/logout"));
					logger.info("Logout returned array: " + result_array.toString());
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					logger.error("Error: " + e);
					returned_error = true;
					e.printStackTrace();
				}
			}
			logger.info("Logout Returning");
			return null;
		}
		
		@Override
	    protected void onPostExecute(Void arg0) {
			 //The data needs to be saved into the database here...
			if(handler != null){
				if(returned_error){
					logger.warning("There was an error with the request. Keep user logged in.");
					handler.sendEmptyMessage(5);
				}else{
					logger.info("Request valid. Logging user out");
					handler.sendEmptyMessage(4);
				}
			}else{
				logger.error("Return handler is null!");
			}
		}
	}
	//send_message_task
	//Make sure that the network is active and working...
		private class send_message_task extends AsyncTask<Void, Void, Void> {
			
			String socket_router;
			JSONObject json;
			ArrayList<NameValuePair> pairs;
			
			send_message_task(ArrayList<NameValuePair> pairs, String socket_router){
				this.pairs = pairs;
				this.socket_router = socket_router;
			}
			
			@Override
	        protected void onPreExecute() {
				logger.info("Sending Message...");
			}
			
			@Override
			protected Void doInBackground(Void... args) {
				synchronized (helper) {
					//message_text
					//try {
						/*JSONObject result_object = new JSONObject(*/helper.postResponsefromURL(this.socket_router, pairs)/*)*/;
						//logger.info(result_object.toString());
					//} catch (JSONException e1) {
						// TODO Auto-generated catch block
					//	e1.printStackTrace();
					//}
				}
				return null;
			}
			
			@Override
		    protected void onPostExecute(Void v) {

			}
		}
}
